﻿namespace SharpF2.ModelView
{
	using System;
	using System.Collections.Generic;
	using System.Collections.ObjectModel;
	using System.ComponentModel;
	using System.IO;
	using System.Linq;
	using System.Text.RegularExpressions;
	using System.Windows;
	using System.Windows.Input;
	using System.Windows.Threading;
	using Commands;
	using Components;
	using Model;
	using Services;
	using View;

	public partial class MainViewViewModel : ViewModelBase
	{
		#region Constructors

		public MainViewViewModel()
		{
			dispatcher = Application.Current.Dispatcher;

			Application.Current.Exit += ApplicationExit;

			LocalIdentifiersViewModel = new IdentifiersViewModel();
			LocalIdentifiersViewModel.UpdateFileItemsEvent += (s, o) => IdentifierChanged();

			SelectedFileItems = new ObservableCollection<FileItem>();
			SelectedTextItems = new ObservableCollection<TextItem>();

			IsRenamable = false;
			StartIndex = 0;

			DirectoryScannerManager.Instance.DirectoryChangeEvent += Directories_DirectoryChangeEvent;
			DirectoryScannerManager.Instance.ObservedFileRenamedEvent += Directories_ObservedFileRenamedEvent;

			WorkingInBackground = false;

			UpdateFileIndexs(FileItems.ToList(), startIndex);
			UpdateColumns();
			InitializeIdentifierColumns();

			fileItemsSortDescription = new SortDescription();
			textItemsSortDescription = new SortDescription();

			WebServices.Instance.PropertyChanged += WebServices_PropertyChanged;
		}

		#endregion

		#region Private Attributes

		private readonly Dispatcher dispatcher;
		private readonly SortableObservableCollection<FileItem> fileItems = new SortableObservableCollection<FileItem>();

		private readonly ObservableCollection<ItemMetaData<IdentifierItem>> identifierColumns =
			new ObservableCollection<ItemMetaData<IdentifierItem>>();

		private readonly SortableObservableCollection<TextItem> textItems = new SortableObservableCollection<TextItem>();

		private DelegateCommand addFilesCommand;
		private DelegateCommand afterDropCommand;
		private Cursor applicationCursor;
		private DelegateCommand clearFilesCommand;
		private DelegateCommand<DragEventArgs> dropItemsCommand;
		private DelegateCommand exitCommand;
		private ObservableCollection<ItemMetaData<FileItem>> fileColumns = new ObservableCollection<ItemMetaData<FileItem>>();
		private List<IdentifierItem> fileIdentifiers = new List<IdentifierItem>();
		private SortDescription fileItemsSortDescription;
		private DelegateCommand<GridViewColumnExtension<FileItem>> fileSortCommand;
		private DelegateCommand generateFilePatternCommandReference;
		private DelegateCommand generateTextPatternCommandReference;
		private Help helpDialog;
		private ObservableCollection<IdentifierItem> identifiers = new ObservableCollection<IdentifierItem>();
		private Boolean isRenamable;
		private IdentifiersViewModel localIdentifiersViewModel;
		private Int32 nbConflicts;
		private Int32 nbFileRegexFails;

		private Int32 nbTextRegexFails;
		private DelegateCommand openAboutDialogCommand;
		private DelegateCommand openFolderCommand;
		private DelegateCommand openHelpDialogCommand;
		private DelegateCommand openOptionsDialogCommand;
		private DelegateCommand openUndoManagerDialogCommand;
		private DelegateCommand openUpdateDialogCommand;
		private DelegateCommand openUserCommentDialogCommand;
		private String outputFilePatternText = String.Empty;

		private String outputFilePatternTextErrorMessage = String.Empty;
		private DelegateCommand pasteCommand;
		private Regex regexInputFile;
		private String regexInputFileFormat = String.Empty;

		private String regexInputFileFormatErrorMessage = String.Empty;
		private Regex regexInputText;
		private String regexInputTextFormat = String.Empty;

		private String regexInputTextFormatErrorMessage = String.Empty;
		private DelegateCommand removeFileCommand;
		private DelegateCommand removeTextCommand;
		private DelegateCommand renameCommand;
		private int startIndex;
		private ObservableCollection<ItemMetaData<TextItem>> textColumns = new ObservableCollection<ItemMetaData<TextItem>>();

		private List<IdentifierItem> textIdentifiers = new List<IdentifierItem>();
		private GridLength textItemsExpandLength;
		private bool textItemsIsExpanded;
		private GridLength textItemsPreviousExpandLength;
		private SortDescription textItemsSortDescription;
		private DelegateCommand<GridViewColumnExtension<TextItem>> textSortCommand;
		private Boolean workingInBackground;

		#endregion

		#region Public Properties

		public ICommand AddFilesCommand
		{
			get
			{
				if (null == addFilesCommand)
					addFilesCommand = new DelegateCommand(ExecuteAddFilesCommand, CanExecuteGeneralCommands);
				return addFilesCommand;
			}
		}

		public ICommand AfterDropCommand
		{
			get
			{
				if (null == afterDropCommand)
					afterDropCommand = new DelegateCommand(ExecuteAfterDropCommand, CanExecuteGeneralCommands);
				return afterDropCommand;
			}
		}

		public Cursor ApplicationCursor
		{
			get { return applicationCursor; }
			set
			{
				if (applicationCursor == value)
					return;

				applicationCursor = value;
				OnPropertyChanged("ApplicationCursor");
			}
		}

		public ICommand ClearFilesCommand
		{
			get
			{
				if (null == clearFilesCommand)
					clearFilesCommand = new DelegateCommand(ExecuteClearFilesCommand, CanExecuteClearFilesCommand);
				return clearFilesCommand;
			}
		}

		public ICommand DropItemsCommand
		{
			get
			{
				if (null == dropItemsCommand)
					dropItemsCommand = new DelegateCommand<DragEventArgs>(ExecuteDropItemsCommand, CanExecuteDropItemsCommands);
				return dropItemsCommand;
			}
		}

		public ICommand ExitCommand
		{
			get
			{
				if (null == exitCommand)
					exitCommand = new DelegateCommand(ExecuteExitCommand);
				return exitCommand;
			}
		}

		public ObservableCollection<ItemMetaData<FileItem>> FileColumns
		{
			get { return fileColumns; }
			set
			{
				fileColumns = value;
				OnPropertyChanged("FileColumns");
			}
		}

		public SortableObservableCollection<FileItem> FileItems
		{
			get { return fileItems; }
		}

		public ICommand FileSortCommand
		{
			get
			{
				if (null == fileSortCommand)
					fileSortCommand = new DelegateCommand<GridViewColumnExtension<FileItem>>(ExecuteFileSortCommand,
					                                                                         CanExecuteFileSortCommand);
				return fileSortCommand;
			}
		}

		public ICommand GenerateFilePatternCommandReference
		{
			get
			{
				if (null == generateFilePatternCommandReference)
					generateFilePatternCommandReference = new DelegateCommand(ExecuteGenerateFilePatternCommandReference,
					                                                          CanExecuteGeneralCommands);
				return generateFilePatternCommandReference;
			}
		}

		public ICommand GenerateTextPatternCommandReference
		{
			get
			{
				if (null == generateTextPatternCommandReference)
					generateTextPatternCommandReference = new DelegateCommand(ExecuteGenerateTextPatternCommandReference,
					                                                          CanExecuteGeneralCommands);
				return generateTextPatternCommandReference;
			}
		}

		public ObservableCollection<ItemMetaData<IdentifierItem>> IdentifierColumns
		{
			get { return identifierColumns; }
		}

		public ObservableCollection<IdentifierItem> Identifiers
		{
			get { return identifiers; }
			set
			{
				LocalIdentifiersViewModel.BackupSelection();
				identifiers = value;
				OnPropertyChanged("Identifiers");
				LocalIdentifiersViewModel.LimitSelection(identifiers);
			}
		}

		public IdentifiersViewModel LocalIdentifiersViewModel
		{
			get { return localIdentifiersViewModel; }
			set
			{
				if (localIdentifiersViewModel == value)
					return;
				localIdentifiersViewModel = value;
				OnPropertyChanged("LocalIdentifiersViewModel");
			}
		}

		public Int32 NbConflicts
		{
			get { return nbConflicts; }
			set
			{
				if (nbConflicts == value)
					return;

				nbConflicts = value;
				OnPropertyChanged("NbConflicts");
			}
		}

		public Int32 NbFileRegexFails
		{
			get { return nbFileRegexFails; }
			set
			{
				if (nbFileRegexFails == value)
					return;

				nbFileRegexFails = value;
				OnPropertyChanged("NbFileRegexFails");
			}
		}

		public Int32 NbTextRegexFails
		{
			get { return nbTextRegexFails; }
			set
			{
				if (nbTextRegexFails == value)
					return;

				nbTextRegexFails = value;
				OnPropertyChanged("NbTextRegexFails");
			}
		}

		public Boolean NewVersionAvailable { get; set; }
		public Boolean NotWorkingInBackground { get; set; }

		public ICommand OpenAboutDialogCommand
		{
			get
			{
				if (null == openAboutDialogCommand)
					openAboutDialogCommand = new DelegateCommand(ExecuteOpenAboutDialogCommand, CanExecuteGeneralCommands);
				return openAboutDialogCommand;
			}
		}

		public ICommand OpenFolderCommand
		{
			get
			{
				if (null == openFolderCommand)
					openFolderCommand = new DelegateCommand(ExecuteOpenFolderCommand, CanExecuteGeneralCommands);
				return openFolderCommand;
			}
		}

		public ICommand OpenHelpDialogCommand
		{
			get
			{
				if (null == openHelpDialogCommand)
					openHelpDialogCommand = new DelegateCommand(ExecuteOpenHelpDialogCommand, CanExecuteGeneralCommands);
				return openHelpDialogCommand;
			}
		}

		public ICommand OpenOptionsDialogCommand
		{
			get
			{
				if (null == openOptionsDialogCommand)
					openOptionsDialogCommand = new DelegateCommand(ExecuteOpenOptionsDialogCommand, CanExecuteGeneralCommands);
				return openOptionsDialogCommand;
			}
		}

		public ICommand OpenUndoManagerDialogCommand
		{
			get
			{
				if (null == openUndoManagerDialogCommand)
					openUndoManagerDialogCommand = new DelegateCommand(ExecuteOpenUndoManagerDialogCommand, CanExecuteGeneralCommands);
				return openUndoManagerDialogCommand;
			}
		}

		public ICommand OpenUpdateDialogCommand
		{
			get
			{
				if (null == openUpdateDialogCommand)
					openUpdateDialogCommand = new DelegateCommand(ExecuteOpenUpdateDialogCommand, CanExecuteOpenUpdateDialogCommand);
				return openUpdateDialogCommand;
			}
		}

		public ICommand OpenUserCommentDialogCommand
		{
			get
			{
				if (null == openUserCommentDialogCommand)
					openUserCommentDialogCommand = new DelegateCommand(ExecuteOpenUserCommentDialogCommand, CanExecuteGeneralCommands);
				return openUserCommentDialogCommand;
			}
		}

		public String OutputFilePatternText
		{
			get { return outputFilePatternText; }
			set
			{
				if (outputFilePatternText == value)
					return;

				outputFilePatternText = value;
				OutputFilePatternChanged();
				OnPropertyChanged("OutputFilePatternText");
			}
		}

		public String OutputFilePatternTextErrorMessage
		{
			get { return outputFilePatternTextErrorMessage; }
			set
			{
				if (outputFilePatternTextErrorMessage == value)
					return;

				outputFilePatternTextErrorMessage = value;
				OnPropertyChanged("OutputFilePatternTextErrorMessage");
			}
		}

		public ICommand PasteCommand
		{
			get
			{
				if (null == pasteCommand)
					pasteCommand = new DelegateCommand(ExecutePasteCommand);
				return pasteCommand;
			}
		}

		public String RegexInputFileFormat
		{
			get { return regexInputFileFormat; }
			set
			{
				if (regexInputFileFormat == value)
					return;

				regexInputFileFormat = value;
				UpdateFileIdentifiers(regexInputFileFormat);

				OnPropertyChanged("RegexInputFileFormat");
				OnPropertyChanged("RegexInputFileFormatErrorMessage");
			}
		}

		public String RegexInputFileFormatErrorMessage
		{
			get { return regexInputFileFormatErrorMessage; }
			set
			{
				if (regexInputFileFormatErrorMessage == value)
					return;

				regexInputFileFormatErrorMessage = value;
				OnPropertyChanged("RegexInputFileFormatErrorMessage");
			}
		}

		public String RegexInputTextFormat
		{
			get { return regexInputTextFormat; }
			set
			{
				if (regexInputTextFormat == value)
					return;

				regexInputTextFormat = value;
				UpdateTextIdentifiers(regexInputTextFormat);

				OnPropertyChanged("RegexInputTextFormat");
				OnPropertyChanged("RegexInputTextFormatErrorMessage");
			}
		}

		public String RegexInputTextFormatErrorMessage
		{
			get { return regexInputTextFormatErrorMessage; }
			set
			{
				if (regexInputTextFormatErrorMessage == value)
					return;

				regexInputTextFormatErrorMessage = value;
				OnPropertyChanged("RegexInputTextFormatErrorMessage");
			}
		}

		public ICommand RemoveFileCommand
		{
			get
			{
				if (null == removeFileCommand)
					removeFileCommand = new DelegateCommand(ExecuteRemoveFileCommand, CanExecuteRemoveFileCommand);
				return removeFileCommand;
			}
		}

		public ICommand RemoveTextCommand
		{
			get
			{
				if (null == removeTextCommand)
					removeTextCommand = new DelegateCommand(ExecuteRemoveTextCommand, CanExecuteRemoveTextCommand);
				return removeTextCommand;
			}
		}

		public ICommand RenameCommand
		{
			get
			{
				if (null == renameCommand)
					renameCommand = new DelegateCommand(ExecuteRenameCommand, CanExecuteRenameCommand);
				return renameCommand;
			}
		}

		public ObservableCollection<FileItem> SelectedFileItems { get; set; }

		public ObservableCollection<TextItem> SelectedTextItems { get; set; }

		public Int32 StartIndex
		{
			get { return startIndex; }
			set
			{
				if (startIndex == value)
					return;
				startIndex = value;
				OutputFilePatternChanged();
				OnPropertyChanged("StartIndex");
			}
		}

		public ObservableCollection<ItemMetaData<TextItem>> TextColumns
		{
			get { return textColumns; }
			set
			{
				textColumns = value;
				OnPropertyChanged("TextColumns");
			}
		}

		public SortableObservableCollection<TextItem> TextItems
		{
			get { return textItems; }
		}

		public GridLength TextItemsExpandLength
		{
			get { return textItemsExpandLength; }
			set
			{
				textItemsExpandLength = value;
				OnPropertyChanged("TextItemsExpandLength");
			}
		}

		public Boolean TextItemsIsExpanded
		{
			get { return textItemsIsExpanded; }
			set
			{
				textItemsIsExpanded = value;
				if (textItemsIsExpanded)
					TextItemsExpandLength = textItemsPreviousExpandLength;
				else
				{
					textItemsPreviousExpandLength = TextItemsExpandLength;
					TextItemsExpandLength = GridLength.Auto;
				}
				OnPropertyChanged("TextItemsIsExpanded");
			}
		}

		public ICommand TextSortCommand
		{
			get
			{
				if (null == textSortCommand)
					textSortCommand = new DelegateCommand<GridViewColumnExtension<TextItem>>(ExecuteTextSortCommand,
					                                                                         CanExecuteTextSortCommand);
				return textSortCommand;
			}
		}

		public Boolean WorkingInBackground
		{
			get { return workingInBackground; }
			set
			{
				workingInBackground = value;
				NotWorkingInBackground = !value;

				DelegateCommandUtility.RaiseCanExecuteChanged(renameCommand);
				DelegateCommandUtility.RaiseCanExecuteChanged(addFilesCommand);
				DelegateCommandUtility.RaiseCanExecuteChanged(openFolderCommand);
				DelegateCommandUtility.RaiseCanExecuteChanged(clearFilesCommand);
				DelegateCommandUtility.RaiseCanExecuteChanged(exitCommand);
				DelegateCommandUtility.RaiseCanExecuteChanged(openOptionsDialogCommand);
				DelegateCommandUtility.RaiseCanExecuteChanged(openUndoManagerDialogCommand);
				DelegateCommandUtility.RaiseCanExecuteChanged(openUserCommentDialogCommand);
				DelegateCommandUtility.RaiseCanExecuteChanged(openAboutDialogCommand);
				DelegateCommandUtility.RaiseCanExecuteChanged(openHelpDialogCommand);
				DelegateCommandUtility.RaiseCanExecuteChanged(fileSortCommand);
				DelegateCommandUtility.RaiseCanExecuteChanged(textSortCommand);
				DelegateCommandUtility.RaiseCanExecuteChanged(removeFileCommand);
				DelegateCommandUtility.RaiseCanExecuteChanged(removeTextCommand);
				DelegateCommandUtility.RaiseCanExecuteChanged(afterDropCommand);
				DelegateCommandUtility.RaiseCanExecuteChanged(dropItemsCommand);
				DelegateCommandUtility.RaiseCanExecuteChanged(openUpdateDialogCommand);
				DelegateCommandUtility.RaiseCanExecuteChanged(generateFilePatternCommandReference);
				DelegateCommandUtility.RaiseCanExecuteChanged(generateTextPatternCommandReference);

				LocalIdentifiersViewModel.WorkingInBackground = value;

				OnPropertyChanged("WorkingInBackground");
				OnPropertyChanged("NotWorkingInBackground");

				ApplicationCursor = workingInBackground ? Cursors.Wait : Cursors.Arrow;
			}
		}

		#endregion

		#region Private Properties

		private Boolean IsRenamable
		{
			get { return isRenamable; }
			set
			{
				isRenamable = value;
				if (null != renameCommand)
					renameCommand.RaiseCanExecuteChanged();
			}
		}

		#endregion

		#region Public Members

		public void AddFile(String filePath)
		{
			if (String.IsNullOrEmpty(filePath)) return;

			var fileItem = new FileItem(filePath);
			if (DirectoryScannerManager.Instance.AddFile(fileItem))
				FileItems.Add(fileItem);

			OutputFilePatternChanged();
		}

		public void AddFiles(IEnumerable<String> filePaths)
		{
			if (null == filePaths) return;

			foreach (var filePath in filePaths)
			{
				var fileItem = new FileItem(filePath);
				if (DirectoryScannerManager.Instance.AddFile(fileItem))
					FileItems.Add(fileItem);
			}

			IdentifierChanged();
		}

		#endregion

		#region Private Members

		private static void ApplicationExit(object sender, ExitEventArgs e)
		{
			OpenUpdateExplorer();
		}

		private static bool CanExecuteOpenUpdateDialogCommand()
		{
			return WebServices.Instance.NewVersionAvailable;
		}

		private static void ExecuteExitCommand()
		{
			Application.Current.Shutdown();
		}

		private static void ExecuteOpenAboutDialogCommand()
		{
			var dialog = new About();
			dialog.ShowDialog();
		}

		private static void ExecuteOpenOptionsDialogCommand()
		{
			var dialog = new Options();
			dialog.ShowDialog();
		}

		private static void ExecuteOpenUndoManagerDialogCommand()
		{
			var dialog = new UndoManagerDialog {DataContext = new UndoManagerDialogModelView()};
			dialog.ShowDialog();
		}

		private static void ExecuteOpenUpdateDialogCommand()
		{
			OpenUpdateExplorer();
		}

		private static void ExecuteOpenUserCommentDialogCommand()
		{
			var dialog = new UserCommentDialog {DataContext = new UserCommentDialogModelView()};
			dialog.ShowDialog();
		}

		private void AddTexts(IEnumerable<String> texts)
		{
			foreach (var text in texts)
				if (!String.IsNullOrEmpty(text))
					TextItems.Add(new TextItem(text));
		}

		private bool CanExecuteClearFilesCommand()
		{
			return FileItems.Count > 0 && !WorkingInBackground;
		}

		private bool CanExecuteDropItemsCommands(DragEventArgs e)
		{
			return !WorkingInBackground;
		}

		private bool CanExecuteFileSortCommand(GridViewColumnExtension<FileItem> column)
		{
			return null == column || WorkingInBackground ? false : column.Sortable;
		}

		private bool CanExecuteGeneralCommands()
		{
			return !WorkingInBackground;
		}

		private bool CanExecuteRemoveFileCommand()
		{
			return null != SelectedFileItems && SelectedFileItems.Count() > 0 && !WorkingInBackground;
		}

		private bool CanExecuteRemoveTextCommand()
		{
			return null != SelectedTextItems && SelectedTextItems.Count() > 0 && !WorkingInBackground;
		}

		private bool CanExecuteRenameCommand()
		{
			return IsRenamable && !WorkingInBackground;
		}

		private bool CanExecuteTextSortCommand(GridViewColumnExtension<TextItem> column)
		{
			return null == column || WorkingInBackground ? false : column.Sortable;
		}

		private void Directories_DirectoryChangeEvent(object sender, FileSystemEventArgs e)
		{
			switch (e.ChangeType)
			{
				case WatcherChangeTypes.Deleted:
					foreach (var fileItem in FileItems)
					{
						if (!fileItem.InputFilePath.Equals(e.FullPath)) continue;
						FileItems.Remove(fileItem);
					}

					OutputFilePatternChanged();
					break;
				default:
					break;
			}
		}

		private void Directories_ObservedFileRenamedEvent(object sender, RenamedEventArgs e)
		{
			foreach (var fileItem in FileItems)
			{
				if (!fileItem.InputFilePath.Equals(e.OldFullPath)) continue;
				fileItem.InputFilePath = e.FullPath;
			}
			OutputFilePatternChanged();
		}

		private void ExecuteAddFilesCommand()
		{
			AddFiles(GetFilesFromFileDialog());
		}

		private void ExecuteAfterDropCommand()
		{
			OutputFilePatternChanged();
		}

		private void ExecuteClearFilesCommand()
		{
			FileItems.Clear();
		}

		private void ExecuteDropItemsCommand(DragEventArgs e)
		{
			if (e.Data is DataObject && ((DataObject) e.Data).ContainsFileDropList())
				AddFiles(((DataObject) e.Data).GetFileDropList().Cast<String>());
			else if (e.Data is DataObject)
				AddTexts(((DataObject) e.Data).GetText().Replace("\n", "").Split('\r'));
		}

		private void ExecuteFileSortCommand(GridViewColumnExtension<FileItem> column)
		{
			if (!column.Sortable) return;

			UpdateSortDescription(column, ref fileItemsSortDescription);

			FileItems.Sort(column.Compare, fileItemsSortDescription.Direction);

			OutputFilePatternChanged();
		}

		private void ExecuteGenerateFilePatternCommandReference()
		{
			var fileNames = new List<String>(FileItems.Select(item => item.InputFileName));
			var localIdentifiers = new List<String>(textIdentifiers.Select(item => item.IdentifierId));

			var bw = new BackgroundWorker();
			bw.DoWork += (o, e) => e.Result = PatternGenerator.GetPattern(fileNames, localIdentifiers);
			bw.RunWorkerCompleted += (o, e) =>
			                         	{
			                         		var result = (KeyValuePair<String, String>) e.Result;
			                         		outputFilePatternText = result.Value;
			                         		RegexInputFileFormat = result.Key;
			                         		OnPropertyChanged("OutputFilePatternText");
			                         		WorkingInBackground = false;
			                         	};
			WorkingInBackground = true;
			bw.RunWorkerAsync();
		}

		private void ExecuteGenerateTextPatternCommandReference()
		{
			var textNames = new List<String>(TextItems.Select(item => item.Text));
			var localIdentifiers = new List<String>(fileIdentifiers.Select(item => item.IdentifierId));

			var bw = new BackgroundWorker();
			bw.DoWork += (o, e) => e.Result = PatternGenerator.GetPattern(textNames, localIdentifiers);
			bw.RunWorkerCompleted += (o, e) =>
			                         	{
			                         		var result = (KeyValuePair<String, String>) e.Result;
			                         		RegexInputTextFormat = result.Key;
			                         		WorkingInBackground = false;
			                         	};
			WorkingInBackground = true;
			bw.RunWorkerAsync();
		}

		private void ExecuteOpenFolderCommand()
		{
			AddFiles(GetFilesFromFolderDialog());
		}

		private void ExecuteOpenHelpDialogCommand()
		{
			if ((null == helpDialog || helpDialog.Focus()) && null != helpDialog) return;

			helpDialog = new Help();
			helpDialog.Show();
		}

		private void ExecutePasteCommand()
		{
			if (!Clipboard.ContainsData(DataFormats.Text))
				return;

			var clipboardData = Clipboard.GetData(DataFormats.Text) as String;

			if (clipboardData != null)
				AddTexts(clipboardData.Replace("\n", "").Split('\r'));
		}

		private void ExecuteRemoveFileCommand()
		{
			if (null != SelectedFileItems)
				RemoveFiles(SelectedFileItems);
		}

		private void ExecuteRemoveTextCommand()
		{
			if (null != SelectedTextItems)
				RemoveTexts(SelectedTextItems);
		}

		private void ExecuteRenameCommand()
		{
			LoggingService.Instance.NewFile();
			foreach (var fileItem in FileItems)
			{
				try
				{
					File.Move(fileItem.InputFilePath, fileItem.OutputFilePath);
					LoggingService.Instance.WriteToLog("Succeed to move file from " + fileItem.InputFilePath + " to " +
					                                   fileItem.OutputFilePath);
				}
				catch (Exception e)
				{
					// Ignore - Log
					LoggingService.Instance.WriteToLog("Fail to move file, Exception source : " + fileItem.InputFilePath + " to " +
					                                   fileItem.OutputFilePath + " " + e.Message);
				}
			}

			OutputFilePatternChanged();
		}

		private void ExecuteTextSortCommand(GridViewColumnExtension<TextItem> column)
		{
			if (!column.Sortable) return;

			UpdateSortDescription(column, ref textItemsSortDescription);

			TextItems.Sort(column.Compare, textItemsSortDescription.Direction);

			OutputFilePatternChanged();
		}

		private void RemoveFiles(IEnumerable<FileItem> files)
		{
			foreach (var fileItem in files)
			{
				FileItems.Remove(fileItem);
				DirectoryScannerManager.Instance.RemoveFileToObservation(fileItem);
			}

			if (0 < files.Count())
				OnPropertyChanged("FileItems");
		}

		private void RemoveTexts(IEnumerable<TextItem> texts)
		{
			foreach (var text in texts)
				TextItems.Remove(text);

			if (0 < texts.Count())
				OnPropertyChanged("TextItems");
		}

		private void WebServices_PropertyChanged(object sender, PropertyChangedEventArgs e)
		{
			if ("NewVersionAvailable".Equals(e.PropertyName))
				NewVersionAvailable = WebServices.Instance.NewVersionAvailable;
		}

		#endregion
	}
}